Skip to content

Fix cross-route fragment scrolling - #163

Open
JoviDeCroock wants to merge 1 commit into
preactjs:mainfrom
JoviDeCroock:fix-cross-route-fragment-scroll
Open

Fix cross-route fragment scrolling#163
JoviDeCroock wants to merge 1 commit into
preactjs:mainfrom
JoviDeCroock:fix-cross-route-fragment-scroll

Conversation

@JoviDeCroock

Copy link
Copy Markdown
Member

Cross-route fragment links did not scroll to their target during app testing because the router reset pushed navigations to the top. This scrolls to the fragment after the destination route commits.

@changeset-bot

changeset-bot Bot commented Aug 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6736bcd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
preact-iso Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@JoviDeCroock

JoviDeCroock commented Aug 23, 2026

Copy link
Copy Markdown
Member Author

Reading up on this more, we should also cover name according to https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-indicated-part-of-the-document

@JoviDeCroock
JoviDeCroock force-pushed the fix-cross-route-fragment-scroll branch from 6e34efb to 6736bcd Compare August 23, 2026 07:57

@rschristian rschristian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a some doubts on the implementation but I see little issue with going forward with this.

The old impl was fairly obviously flawed but, IME, actually worked as expected the majority of the time, I believe due to scrollTo actually getting called early and natural browser scrolling kicking in after the route component actually fulled rendered. I think we'd need to wait for the current route to fully render before attempting to scroll programmatically if we want to be correct.

Comment thread src/router.js
Comment on lines +33 to +35
Array.from(document.getElementsByName(fragment)).find(
element => element.localName == 'a'
);

@rschristian rschristian Aug 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that we really need to support this, as it's super niche, but this can be done simpler:

Suggested change
Array.from(document.getElementsByName(fragment)).find(
element => element.localName == 'a'
);
document.querySelector(`a[name="${fragment}"`);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to avoid potential CSS injection issues mainly

Comment thread test/router.test.js
@JoviDeCroock

JoviDeCroock commented Aug 24, 2026

Copy link
Copy Markdown
Member Author

Agree, I do think that a full solution would require us to be integrated with data-fetching, ... so that we are aware of full route readiness. The current thing covers async routes and synchronous routes but not routes that load data and then render UI. For my tests in drydock this has been a step in the right direction though as before this hash based routing (i.e. scroll to my docs link) would never apply basically

@rschristian

Copy link
Copy Markdown
Member

hash based routing (i.e. scroll to my docs link) would never apply basically

Ah, that's no good.

Surprisingly the Preact docs site works pretty well (IME) at this, despite, with prefetching, most route swaps being synchronous. I'd expect the previous scrollTo to be problematic for sync but that hasn't seemed to be the case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants